#ifndef __UNAME_POOL_PROCESSPOOL_HPP__
#define __UNAME_POOL_PROCESSPOOL_HPP__
#include <iostream>
#include <vector>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdlib>
#include "Task.hpp"
// 线描述再组织
class Channel
{
public:
    Channel(int f, pid_t p) : _write_fd(f), _sub_pid(p)
    {
        _name = "channel  " + std::to_string(_write_fd) + "  +  " + std::to_string(_sub_pid);
        // to_string 将整数转换为字符串
    }
    int Fd()
    {
        return _write_fd;
    }
    int SubPid()
    {
        return _sub_pid;
    }
    void send(int code)
    {
        int n = write(_write_fd, &code, sizeof(code));
        (void)n;
    }
    void Wait()
    {
        pid_t t = waitpid(_sub_pid, nullptr, 0);
        (void)t;
    }
    std::string Name()
    {
        return _name;
    }

    void Close()
    {
        close(_write_fd);
    }
    ~Channel() {}

private:
    int _write_fd;
    pid_t _sub_pid;
    std::string _name; // 线程名称
};

// 在组织
class ChannelManager
{
public:
    void insert(int write_fd, int pid);
    void PrintChannels()
    {
        for (auto &c : _channels)
        {

            std::cout << c.Name() << std::endl;
        }
    }
    Channel &Select()
    {
        // 负载均衡
        Channel &c = _channels[_index];
        _index = (_index + 1) % _channels.size();
        return c;
    }
    void ChannelProcess_Stop() // 关闭所有的子进程
    {
        for (auto &x : _channels)
        {
            x.Close();
            std::cout << "关闭了信道:" << x.Name() << std::endl;
        }
    }
    void WaitAll() // 回收所有的子进程
    {
        for (auto &x : _channels)
        {
            x.Wait();
            std::cout << "回收子进程:" << x.Name() << std::endl;
        }
    }
    ChannelManager() : _index(0) {}
    ~ChannelManager() {}

private:
    std::vector<Channel> _channels;
    int _index = 0; // 负载均衡
};

void ChannelManager::insert(int write_fd, pid_t pid)
{
    // 或者 _channels.emplace_back(write_fd, pid);
    Channel c(write_fd, pid);
    _channels.push_back(std::move(c));
}

class ProcessPool
{
private:
    ChannelManager _channel_manager;
    int _process_num;
    TaskManager _task_manager;
    /* data */
public:
    ProcessPool(int num = 4) : _process_num(num)
    {
        // 注册任务
        _task_manager.register_task(Print_log);
        _task_manager.register_task(Download_file);
        _task_manager.register_task(Upload_file);
        // _task_manager.register_task(Compress_file);
    }
    void StopAll()
    {
        _channel_manager.ChannelProcess_Stop(); // 关闭所有的子进程
        _channel_manager.WaitAll();             // 回收所有的子进程
    }

    void Work(int write_fd);
    void Run()
    {
        // 1 选择一个任务
        int task_io_code = _task_manager.Code();

        // 1 选择一个信道 负载均很的选择一个子进程 完成任务
        auto &c = _channel_manager.Select();
        std::cout << "主进程选择了信道:" << c.Name() << std::endl;
        // std::cout << std::endl;
        // sleep(2);
        // std::cout << std::endl;
        // 2 通过信道发送任务码
        c.send(task_io_code);
        std::cout << " 发送任务码:" << task_io_code << std::endl;
    }
    bool create();
    void debug()
    {
        _channel_manager.PrintChannels();
    }
    ~ProcessPool()
    {
    }
};

void ProcessPool::Work(int write_fd)
{
    int code = 0;
    while (true)
    {
        // std::cout << "我是子进程我的_fd是:" << write_fd << std::endl;
        // std::cout << std::endl;
        // sleep(5);
        code = 0;
        ssize_t s = read(write_fd, &code, sizeof(code));
        if (s > 0)
        {
            if (s != sizeof(code))
            {
                continue;
            }
            std::cout << "子进程[" << getpid() << "]收到一个任务码：" << code << std::endl;
            _task_manager.Execute(code);
        }
        else if (s == 0)
        {
            std::cout << "child process:" << getpid() << " pipe closed" << std::endl;
            break;
        }
        else
        {

            std::cout << "read error" << std::endl;
            break;
        }
    }
}

bool ProcessPool::create()
{
    for (int i = 0; i < _process_num; ++i)
    {
        // 1 创建管道
        int pipefd[2] = {0};
        if (pipe(pipefd) < 0)
        {
            std::cerr << "pipe error" << std::endl;
            return false;
        }
        // 2创建子进程
        pid_t pid = fork();
        if (pid < 0)
        {
            std::cerr << "fork error" << std::endl;
            return false;
        }
        else if (pid == 0) // child
        {
            close(pipefd[1]); // 关闭写端
            Work(pipefd[0]);  // 子进程工作函数
            close(pipefd[0]); // 关闭读端
                              //  std::cout << "child process:" << getpid() << std::endl;
            exit(0);
        }
        else // parent
        {
            close(pipefd[0]); // 关闭读端
            /*
            已知子进程的pid 和 write_fd
            */
            _channel_manager.insert(pipefd[1], pid);
            // std::cout << "parent process:" << getpid() << " create child process:" << pid << std::endl;
        }
    }
    return true;
}

#endif // !__UNAME_POOL_PROCESSPOOL_HPP__
